package com.example.app.service.impl;

import com.example.app.constants.StateConstants;
import com.example.app.model.Organ;
import com.example.app.model.SystemConfig;
import com.example.app.model.User;
import com.example.app.service.AttendanceService;
import com.example.app.service.OrganService;
import com.example.app.service.SystemConfigService;
import com.example.app.service.UserService;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by wangtao on 2018/5/22.
 */
@Service
public class AttendanceServiceImpl implements AttendanceService {

    @PersistenceContext
    EntityManager em;

    @Autowired
    private SQLManager sqlManager;

    @Autowired
    private UserService userService;

    @Autowired
    private SystemConfigService configService;

    @Autowired
    private OrganService organService;

    @Override
    public List<User> getHealthcare(Long organId, String dateStr, int appointType, int process) throws ParseException {
        List<User> resultList = new ArrayList<>();
        List<Long> canNotList = new ArrayList<>();
        Organ organ = organService.findOneFromCache(organId);
        // 只有预约到店的需要限制预约次数
        if (process == StateConstants.RESERVATION_PROCESS_ARRIVAL) {
            SystemConfig config = configService.findOne(organ.getAccountId(), organId);
            if (config != null) {
                // 日期字符串转换成日期类型
                Date appointment = DateUtils.parseDate(dateStr, new String[]{"yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss"});
                // 预约时间年月日
                String ymd = dateStr.substring(0, dateStr.indexOf(" "));
                if (config.getDoctorReceptionOld() > 0 || config.getDoctorReceptionNew() > 0) {
                    // 医生接诊时间间隔
                    int hours = config.getDoctorInterval();
                    // 开始工作时间
                    Date startDate = DateUtils.parseDate(ymd + " 10:00:00", new String[]{"yyyy-MM-dd HH:mm:ss"});
                    Date endDate = DateUtils.addHours(startDate, hours);
                    while (true){
                        // 大于计算开始时间，小于计算结束时间，表示已匹配到计算时区
                        if (appointment.compareTo(startDate) >= 0 && appointment.compareTo(endDate) < 0) {
                            break;
                        }
                        startDate = DateUtils.addHours(startDate, hours);
                        endDate = DateUtils.addHours(endDate, hours);
                    }
                    String startDateStr = DateFormatUtils.format(startDate, "yyyy-MM-dd HH:mm:ss");
                    String endDateStr = DateFormatUtils.format(endDate, "yyyy-MM-dd HH:mm:ss");
                    // 查询所有医生在预约时间当天的预约次数
                    StringBuilder sql = new StringBuilder("select doctor_id as userId,type,COUNT(1) as count from business_visit_record");
                    sql.append(" where account_id = " + organ.getAccountId());
                    sql.append(" and organ_id = " + organ.getId());
                    sql.append(" and appointment BETWEEN '" + startDateStr + "' and '" + endDateStr + "'");
                    sql.append(" GROUP BY doctor_id,type");
                    List<Map> mapList = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
                    // 复诊预约
                    if (appointType == StateConstants.RESERVATION_TYPE_OLD && config.getDoctorReceptionOld() > 0) {
                        for (Map map : mapList) {
                            Long userId = Long.valueOf(map.get("userId").toString());
                            int type = Integer.parseInt(map.get("type").toString());
                            // 已预约次数
                            int count = Integer.parseInt(map.get("count").toString());
                            if (appointType == type) {
                                if (count >= config.getDoctorReceptionOld()) {
                                    canNotList.add(userId);
                                }
                            }
                        }
                        // 新诊预约
                    } else if (appointType == StateConstants.RESERVATION_TYPE_NEW && config.getDoctorReceptionNew() > 0) {
                        for (Map map : mapList) {
                            Long userId = Long.valueOf(map.get("userId").toString());
                            int type = Integer.parseInt(map.get("type").toString());
                            // 已预约次数
                            int count = Integer.parseInt(map.get("count").toString());
                            if (appointType == type) {
                                if (count >= config.getDoctorReceptionOld()) {
                                    canNotList.add(userId);
                                }
                            }
                        }
                    }
                }
                if (config.getNurseReceptionOld() > 0 || config.getNurseReceptionNew() > 0) {
                    // 护士接诊时间间隔
                    int hours = config.getNurseInterval();
                    // 开始工作时间
                    Date startDate = DateUtils.parseDate(ymd + " 10:00:00", new String[]{"yyyy-MM-dd HH:mm:ss"});
                    Date endDate = DateUtils.addHours(startDate, hours);
                    while (true){
                        // 大于计算开始时间，小于计算结束时间，表示已匹配到计算时区
                        if (appointment.compareTo(startDate) >= 0 && appointment.compareTo(endDate) < 0) {
                            break;
                        }
                        startDate = DateUtils.addHours(startDate, hours);
                        endDate = DateUtils.addHours(endDate, hours);
                    }
                    // 查询所有护士在预约时间当天的预约次数
                    StringBuilder sql = new StringBuilder("select nurse_id as userId,type,COUNT(1) as count from business_visit_record");
                    sql.append(" where account_id = " + organ.getAccountId());
                    sql.append(" and organ_id = " + organ.getId());
                    sql.append(" and appointment BETWEEN '" + DateFormatUtils.format(startDate, "yyyy-MM-dd HH:mm:ss") + "' and '" + DateFormatUtils.format(endDate, "yyyy-MM-dd HH:mm:ss") + "'");
                    sql.append(" GROUP BY nurse_id,type");
                    List<Map> mapList = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
                    // 复诊预约
                    if (appointType == StateConstants.RESERVATION_TYPE_OLD && config.getNurseReceptionOld() > 0) {
                        for (Map map : mapList) {
                            Long userId = Long.valueOf(map.get("userId").toString());
                            int type = Integer.parseInt(map.get("type").toString());
                            // 已预约次数
                            int count = Integer.parseInt(map.get("count").toString());
                            if (appointType == type) {
                                if (count >= config.getNurseReceptionOld()) {
                                    canNotList.add(userId);
                                }
                            }
                        }
                        // 新诊预约
                    } else if (appointType == StateConstants.RESERVATION_TYPE_NEW && config.getNurseReceptionNew() > 0) {
                        for (Map map : mapList) {
                            Long userId = Long.valueOf(map.get("userId").toString());
                            int type = Integer.parseInt(map.get("type").toString());
                            // 已预约次数
                            int count = Integer.parseInt(map.get("count").toString());
                            if (appointType == type) {
                                if (count >= config.getNurseReceptionNew()) {
                                    canNotList.add(userId);
                                }
                            }
                        }
                    }
                }
            }
        }
        // 获取所有医护工作人员集合
        String idsStr = "";
        List<User> users = userService.findHealthcareFromCache(organ.getAccountId(), organ.getId());
        for (User user : users) {
            idsStr += user.getId() + ",";
        }
        idsStr = idsStr.substring(0, idsStr.lastIndexOf(","));
        // 查询当天休息的
        StringBuilder sql = new StringBuilder("select user_id as userId from attendance_record");
        sql.append(" where user_id in(" + idsStr + ")");
        sql.append(" and record_type = " + StateConstants.ATTENDANCE_RECORD_TYPE_LEAVE);
        sql.append(" and status = " + StateConstants.ATTENDANCE_STATUS_AGREE);
        sql.append(" and start_time <= '" + dateStr + "'");
        sql.append(" and end_time >= '" + dateStr + "'");
        List<Map> mapList = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
        for (Map map : mapList) {
            canNotList.add(Long.valueOf(map.get("userId").toString()));
        }
        // 过滤掉不符合条件的
        List<User> doctorList = new ArrayList<>();
        List<User> nurseList = new ArrayList<>();
        for (User user : users) {
            if (!canNotList.contains(user.getId())) {
                resultList.add(user);
            }
        }
        // 返回符合条件的
        return resultList;
    }

    @Override
    public boolean checkByUserId(Long userId, String datetime) {
        // 查询当天是否休息
        StringBuilder sql = new StringBuilder("select count(1) as count from attendance_record");
        sql.append(" where user_id = " + userId);
        sql.append(" and record_type = " + StateConstants.ATTENDANCE_RECORD_TYPE_LEAVE);
        sql.append(" and status = " + StateConstants.ATTENDANCE_STATUS_AGREE);
        sql.append(" and start_time <= '" + datetime + "'");
        sql.append(" and end_time >= '" + datetime + "'");
        List<Map> list = sqlManager.execute(new SQLReady(sql.toString()), Map.class);
        int count = Integer.parseInt(list.get(0).get("count").toString());
        return count == 0;
    }
}
